#include "winimehandler.h"
#include <QApplication>
#include <QKeyEvent>
#include <QDebug>

extern "C" BOOL WINAPI ImmUninstallIME(HKL hkl, LPCWSTR lpszIMEFileName);
extern "C" BOOL WINAPI ImmSetCandidateList(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandidateList, DWORD dwBufLen);


// 静态实例初始化
WinIMEHandler* WinIMEHandler::m_instance = nullptr;

WinIMEHandler::WinIMEHandler(InputContext* inputCtx, QObject* parent)
    : QObject(parent)
    , m_inputCtx(inputCtx)
    , m_activeHwnd(nullptr)
    , m_imeContext(nullptr)
    , m_isChineseMode(true)
{
    m_instance = this;
    // 关联InputContext信号（候选词更新、状态变更）
    connect(m_inputCtx, &InputContext::candidatesUpdated, this, &WinIMEHandler::onCandidatesUpdated);
    connect(m_inputCtx, &InputContext::stateChanged, this, &WinIMEHandler::onInputStateChanged);
    // 关联自身信号到InputContext（转发系统事件、候选词选择）
    connect(this, &WinIMEHandler::systemKeyEvent, m_inputCtx, &InputContext::handleKeyEvent);
    connect(this, &WinIMEHandler::candidateSelectedBySystem, m_inputCtx, &InputContext::selectCandidate);
}

WinIMEHandler::~WinIMEHandler() {
    if (m_imeContext) {
        ImmDestroyContext(m_imeContext);
    }
    m_instance = nullptr;
}

// 注册IME到系统（需管理员权限）
bool WinIMEHandler::registerIME(const QString& imeName, const QString& imePath) {
    // 转换为宽字符（imm32.dll要求）
    std::wstring wsImeName = imeName.toStdWString();
    std::wstring wsImePath = imePath.toStdWString();
    
    // 注册IME（ImmInstallIME返回非0表示成功）
    HKL result = ImmInstallIME(wsImePath.c_str(), wsImeName.c_str());
	if (result == NULL) { // 失败判断
	    qWarning() << "[WinIME] 注册失败，错误码：" << GetLastError();
	    return false;
	}
    qInfo() << "[WinIME] 注册成功，IME名称：" << imeName;
    return true;
}

// 卸载IME
bool WinIMEHandler::unregisterIME(const QString& imePath) {
    std::wstring wsImePath = imePath.toStdWString();
    BOOL result = ImmUninstallIME(nullptr, wsImePath.c_str());
    if (result == 0) {
        qWarning() << "[WinIME] 卸载失败，错误码：" << GetLastError();
        return false;
    }
    qInfo() << "[WinIME] 卸载成功";
    return true;
}

// 设置当前激活窗口
void WinIMEHandler::setActiveWindow(HWND hwnd) {
    if (m_activeHwnd == hwnd) return;
    m_activeHwnd = hwnd;
    
    // 为新窗口创建IME上下文
    if (m_imeContext) {
        ImmDestroyContext(m_imeContext);
    }
    m_imeContext = ImmCreateContext();
    if (!m_imeContext) {
        qWarning() << "[WinIME] 创建IME上下文失败";
    }
}

// 接收InputContext的候选词，同步到系统
void WinIMEHandler::onCandidatesUpdated(const QVector<PinyinCandidate>& candidates) {
    if (!m_imeContext || candidates.isEmpty()) return;
    
    // 转换为系统候选词结构
    m_systemCandidates.clear();
    for (int i = 0; i < candidates.size(); ++i) {
        m_systemCandidates.append({ candidates[i].text, static_cast<DWORD>(i + 1) });  // 系统索引从1开始
    }
    
    // 通知系统更新候选词（发送IMN_SETCANDIDATEPOS消息）
    ImmNotifyIME(m_imeContext, NULL, IMN_SETCANDIDATEPOS, 0);
    qDebug() << "[WinIME] 同步候选词到系统：" << candidates.size() << "个";
}

// 接收InputContext的状态变更，更新IME模式
void WinIMEHandler::onInputStateChanged(const InputState& state) {
    m_isChineseMode = (state.inputMode == ChineseMode || state.inputMode == SimplifiedMode || state.inputMode == TraditionalMode);
    qDebug() << "[WinIME] 模式更新：" << (m_isChineseMode ? "中文" : "英文");
}

// IME核心回调函数（处理系统发送的IME消息）
LRESULT CALLBACK WinIMEHandler::IMEProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if (!m_instance || !m_instance->m_imeContext) {
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    
    switch (msg) {
        // 处理键盘事件
        case WM_KEYDOWN:
            m_instance->processSystemKeyEvent(m_instance->m_imeContext, wParam, lParam);
            return 0;  // 标识IME已处理事件，避免系统重复处理
        
        // 处理候选词请求（系统需要显示候选词时触发）
        case WM_IME_NOTIFY:
            if (lParam == IMN_OPENCANDIDATE) {
                m_instance->handleCandidateRequest(m_instance->m_imeContext, lParam);
            }
            break;
        
        // 处理候选词选择（用户在系统候选词窗口选择时触发）
        case WM_IME_SELECT:
            if (wParam == 1) {  // 1表示选中候选词
                DWORD selectedIndex = ImmGetCandidateList(m_instance->m_imeContext, 0, nullptr, 0);
                if (selectedIndex > 0) {
                    m_instance->emit candidateSelectedBySystem(static_cast<int>(selectedIndex - 1));  // 转换为0-based索引
                }
            }
            break;
        
        default:
            break;
    }
    
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

// 处理系统键盘事件，转换为Qt KeyEvent
void WinIMEHandler::processSystemKeyEvent(HIMC himc, WPARAM wParam, LPARAM lParam) {
    if (!m_activeHwnd) return;
    
    // 提取键盘事件信息（是否按下、修饰键）
    bool isPressed = true;
    Qt::KeyboardModifiers modifiers = Qt::NoModifier;
    if (lParam & 0x40000000) {  // 键已释放
        isPressed = false;
    }
    if (lParam & 0x00010000) {  // Shift键
        modifiers |= Qt::ShiftModifier;
    }
    if (lParam & 0x00080000) {  // Ctrl键
        modifiers |= Qt::ControlModifier;
    }
    if (lParam & 0x00800000) {  // Alt键
        modifiers |= Qt::AltModifier;
    }
    
    // 转换系统键码为Qt键码
    Qt::Key key = static_cast<Qt::Key>(wParam);
    QString text = QKeySequence(key).toString();
    
    // 创建Qt KeyEvent并转发给InputContext
    QKeyEvent* event = new QKeyEvent(isPressed ? QEvent::KeyPress : QEvent::KeyRelease, key, modifiers, text);
    QApplication::postEvent(this, event);  // 用postEvent避免阻塞系统消息循环
}

// 处理系统候选词请求，返回候选词数据
void WinIMEHandler::handleCandidateRequest(HIMC himc, LPARAM lParam) {
    if (m_systemCandidates.isEmpty()) return;
    
    // 计算候选词列表大小
    DWORD candidateSize = sizeof(CANDIDATELIST) + (m_systemCandidates.size() - 1) * sizeof(DWORD);
    for (const auto& cand : m_systemCandidates) {
        candidateSize += cand.text.toWCharArray(nullptr) + 1;  // 包含终止符
    }
    
    // 分配内存存储候选词列表
    LPVOID candidateBuf = LocalAlloc(LMEM_FIXED, candidateSize);
    if (!candidateBuf) return;
    
    CANDIDATELIST* candidateList = static_cast<CANDIDATELIST*>(candidateBuf);
    candidateList->dwSize = sizeof(CANDIDATELIST);
    candidateList->dwCount = static_cast<DWORD>(m_systemCandidates.size());
    candidateList->dwSelection = 0;  // 默认选中第一个
    candidateList->dwPageStart = 0;
    candidateList->dwPageSize = candidateList->dwCount;
    
    // 填充候选词索引和文本
    DWORD* pIndex = candidateList->dwOffset;
    WCHAR* pText = reinterpret_cast<WCHAR*>(candidateList + 1);
    for (const auto& cand : m_systemCandidates) {
        *pIndex = reinterpret_cast<DWORD>(pText) - reinterpret_cast<DWORD>(candidateList);
        pText += cand.text.toWCharArray(pText) + 1;  // 写入文本并移动指针
        pIndex++;
    }
    
    // 将候选词列表返回给系统
    ImmSetCandidateList(himc, 0, candidateList, candidateSize);
    LocalFree(candidateBuf);
}

// 同步输入文本到系统输入框
void WinIMEHandler::syncCompositionTextToSystem(HIMC himc, const QString& text) {
    if (!himc || text.isEmpty()) return;
    
    // 转换为宽字符（UTF-16，符合Windows API要求）
    std::wstring wsText = text.toStdWString();
    int textLength = (wsText.size() + 1) * sizeof(WCHAR);  // 包含终止符'\0'的长度（按字节计算）
    
    // 使用 GCS_COMPSTR 替代 SCS_SETCOMPSTR，指定设置组合字符串
    ImmSetCompositionStringW(himc, GCS_COMPSTR,
                             const_cast<LPWSTR>(wsText.c_str()),
                             textLength,
                             nullptr, 0);
}